package com.example.gpu;

import java.util.stream.IntStream;

/**
 * CPU-only版本的向量运算示例
 * 这个版本不需要CUDA或GPU支持，可以在任何Java环境中运行
 * 用于演示向量运算的基本概念，即使没有GPU环境也能学习
 */
public class CPUOnlyExample {
    
    public static void main(String[] args) {
        System.out.println("Java CPU向量运算示例");
        System.out.println("================================");
        
        // 向量大小 - 可以根据需要调整
        int vectorSize = 1000000;
        
        // 创建和初始化输入向量
        float[] vectorA = new float[vectorSize];
        float[] vectorB = new float[vectorSize];
        float[] vectorC = new float[vectorSize];
        
        System.out.println("初始化向量数据...");
        for (int i = 0; i < vectorSize; i++) {
            vectorA[i] = (float)i;
            vectorB[i] = (float)(vectorSize - i);
        }
        
        try {
            // 执行向量加法运算
            performVectorAddition(vectorA, vectorB, vectorC, vectorSize);
            
            // 执行并行向量加法运算（使用Java并行流）
            performParallelVectorAddition(vectorA, vectorB, vectorC, vectorSize);
            
            // 执行向量点积运算
            performVectorDotProduct(vectorA, vectorB, vectorSize);
            
            // 执行矩阵乘法模拟
            performMatrixMultiplicationDemo(vectorSize);
            
        } catch (Exception e) {
            System.err.println("执行计算时出错: " + e.getMessage());
            e.printStackTrace();
        }
        
        System.out.println("\n================================");
        System.out.println("注意: 这是CPU-only版本。要体验GPU加速版本，");
        System.out.println("请按照CUDA_COMPILER_SETUP_GUIDE.md中的说明设置环境。");
    }
    
    /**
     * 基本的向量加法实现
     */
    private static void performVectorAddition(float[] a, float[] b, float[] c, int n) {
        System.out.println("\n执行基本向量加法...");
        
        // 计时开始
        long startTime = System.currentTimeMillis();
        
        // 执行向量加法运算
        for (int i = 0; i < n; i++) {
            c[i] = a[i] + b[i];
        }
        
        // 计时结束
        long endTime = System.currentTimeMillis();
        
        System.out.println("向量大小: " + n);
        System.out.println("计算耗时: " + (endTime - startTime) + " ms");
        
        // 显示前10个结果
        System.out.println("前10个计算结果: ");
        for (int i = 0; i < Math.min(10, n); i++) {
            System.out.printf("c[%d] = %.1f\n", i, c[i]);
        }
    }
    
    /**
     * 使用Java并行流的并行向量加法实现
     */
    private static void performParallelVectorAddition(float[] a, float[] b, float[] c, int n) {
        System.out.println("\n执行并行向量加法（使用Java并行流）...");
        
        // 创建新的结果数组
        float[] parallelResult = new float[n];
        
        // 计时开始
        long startTime = System.currentTimeMillis();
        
        // 使用Java并行流执行向量加法
        IntStream.range(0, n).parallel().forEach(i -> {
            parallelResult[i] = a[i] + b[i];
        });
        
        // 计时结束
        long endTime = System.currentTimeMillis();
        
        System.out.println("向量大小: " + n);
        System.out.println("并行计算耗时: " + (endTime - startTime) + " ms");
        
        // 验证并行计算结果是否正确
        boolean correct = true;
        for (int i = 0; i < n; i++) {
            if (Math.abs(parallelResult[i] - c[i]) > 1e-6) {
                correct = false;
                break;
            }
        }
        System.out.println("并行计算结果验证: " + (correct ? "通过" : "失败"));
    }
    
    /**
     * 向量点积运算实现
     */
    private static void performVectorDotProduct(float[] a, float[] b, int n) {
        System.out.println("\n执行向量点积运算...");
        
        // 计时开始
        long startTime = System.currentTimeMillis();
        
        // 执行向量点积运算
        float dotProduct = 0.0f;
        for (int i = 0; i < n; i++) {
            dotProduct += a[i] * b[i];
        }
        
        // 计时结束
        long endTime = System.currentTimeMillis();
        
        System.out.println("向量大小: " + n);
        System.out.println("计算耗时: " + (endTime - startTime) + " ms");
        System.out.printf("点积结果: %.2f\n", dotProduct);
    }
    
    /**
     * 矩阵乘法模拟（小型矩阵）
     */
    private static void performMatrixMultiplicationDemo(int vectorSize) {
        // 为了演示，使用较小的矩阵
        int matrixSize = 1000; // 矩阵维度
        
        System.out.println("\n执行矩阵乘法模拟 (" + matrixSize + "x" + matrixSize + ")...");
        
        // 创建矩阵
        float[][] matrixA = new float[matrixSize][matrixSize];
        float[][] matrixB = new float[matrixSize][matrixSize];
        float[][] matrixC = new float[matrixSize][matrixSize];
        
        // 初始化矩阵数据
        for (int i = 0; i < matrixSize; i++) {
            for (int j = 0; j < matrixSize; j++) {
                matrixA[i][j] = (float)Math.random();
                matrixB[i][j] = (float)Math.random();
            }
        }
        
        // 计时开始
        long startTime = System.currentTimeMillis();
        
        // 执行矩阵乘法
        for (int i = 0; i < matrixSize; i++) {
            for (int j = 0; j < matrixSize; j++) {
                matrixC[i][j] = 0.0f;
                for (int k = 0; k < matrixSize; k++) {
                    matrixC[i][j] += matrixA[i][k] * matrixB[k][j];
                }
            }
        }
        
        // 计时结束
        long endTime = System.currentTimeMillis();
        
        System.out.println("矩阵维度: " + matrixSize + "x" + matrixSize);
        System.out.println("计算耗时: " + (endTime - startTime) + " ms");
        
        // 显示左上角4x4的结果
        System.out.println("结果矩阵左上角4x4部分: ");
        for (int i = 0; i < Math.min(4, matrixSize); i++) {
            for (int j = 0; j < Math.min(4, matrixSize); j++) {
                System.out.printf("%.2f\t", matrixC[i][j]);
            }
            System.out.println();
        }
        
        System.out.println("\n注意: 在实际应用中，矩阵乘法在GPU上可以比CPU快数十倍！");
    }
}